// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System;
using System.Collections.Generic;

namespace SnapObjects.Data
{
    internal class UpdatableBuilder
    {
        protected readonly IMapperContext _mapperContext;
        private readonly IList<IUpdatableModel> _updatableModels;

        public UpdatableBuilder(IMapperContext mapperContext)
        {
            _mapperContext = mapperContext;
            _updatableModels = new List<IUpdatableModel>();
        }

        public IReadOnlyList<IUpdatableModel> UpdatableModels =>
                    _updatableModels as IReadOnlyList<IUpdatableModel>;

        public void Reset()
        {
            _updatableModels.Clear();
        }

        public void Append(
            Type modelType,
            ICompositeModelAccessor compositeModelAccessor,
            PocoModelMeta modelMeta,
            object model,
            ModelState modelState,
            bool checkLastState,
            Action<ISaveContext> beforeSaveAction,
            Action<ISaveContext> afterSaveAction)
        {
            var statefulModel = PocoStatefulModelFactory.Create(modelType,
                                                compositeModelAccessor, model, modelState, ChangeTrackingStrategy.Snapshot);

            var updatableModelType = typeof(UpdatableModel<>).MakeGenericType(
                                    new Type[] { modelType });

            var updatableModel = (IUpdatableModel)Activator.CreateInstance(
                                        updatableModelType,
                                        new object[] { modelMeta,
                                                    ChangeTrackingStrategy.Snapshot,
                                                    modelMeta.UpdateWhereStrategy,
                                                    statefulModel,
                                                    checkLastState,
                                                    beforeSaveAction,
                                                    afterSaveAction,
                                                    null});

            _updatableModels.Add(updatableModel);
        }

        public void Append(
            Type modelType,
            ICompositeModelAccessor compositeModelAccessor,
            object model,
            ModelState modelState)
        {
            var modelMeta = ModelMetaManager.GetModelMeta(modelType);
            var statefulModel = PocoStatefulModelFactory.Create(modelType,
                                                compositeModelAccessor, model, modelState, ChangeTrackingStrategy.Snapshot);

            _updatableModels.Add(new UpdatableModel(
                                        modelMeta,
                                        ChangeTrackingStrategy.Snapshot,
                                        modelMeta.UpdateWhereStrategy,
                                        statefulModel,
                                        true));
        }

        public void Append(IUpdatableModel updatableModel)
        {
            _updatableModels.Add(updatableModel);
        }

        public void Append(IReadOnlyList<IUpdatableModel> updatableModels)
        {
            foreach (var updatableModel in updatableModels)
            {
                _updatableModels.Add(updatableModel);
            }
        }
    }
}
